package com.lz.library.adapter

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil.DiffResult
import androidx.recyclerview.widget.RecyclerView
import com.lz.library.extension.APP

/**
 *  author: you : 2020/4/25
 */
abstract class BaseAdapter<T, VH : RecyclerView.ViewHolder>(initData: List<T>? = null) : RecyclerView.Adapter<VH>(),
    com.lz.library.adapter.IAdapter<T> {

    private val mInflater: LayoutInflater = LayoutInflater.from(APP)

    private val mData = ArrayList<T>()

    //adapter view click call back
    private var onItemClickListener: com.lz.library.adapter.BaseAdapter.OnItemClickListener? = null

    //adapter view long click call back
    private var onItemLongClickListener: com.lz.library.adapter.BaseAdapter.OnItemLongClickListener? = null

    init {
        initData?.also { mData.addAll(it) }
    }

    override fun getItemCount(): Int = mData.size

    final override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH =
        onCreateItem(parent, viewType).apply { onItemCreated(this, viewType); initItemClickListener(this) }

    protected abstract fun onCreateItem(parent: ViewGroup, viewType: Int): VH

    //可以做些子控件的事件绑定
    protected open fun onItemCreated(vh: VH, viewType: Int) {}

    open fun getItemPosition(vh: VH): Int = vh.bindingAdapterPosition

    /**
     * 初始化ViewHolder点击事件
     *
     * @param vh
     */
    open fun initItemClickListener(vh: VH) {
        if (onItemClickListener != null) {
            vh.itemView.setOnClickListener { v -> onItemClickListener!!.onItemClick(v, getItemPosition(vh)) }
        }
        if (onItemLongClickListener != null) {
            vh.itemView.setOnLongClickListener { v -> onItemLongClickListener!!.onItemLongClick(v, getItemPosition(vh)) }
        }
    }

    /**
     * Register a callback in this AdapterView has been clicked.
     *
     * @param onItemClickListener
     */
    fun setOnItemClickListener(onItemClickListener: com.lz.library.adapter.BaseAdapter.OnItemClickListener?) {
        this.onItemClickListener = onItemClickListener
    }

    /**
     * Register a callback in this AdapterView has been long clicked.
     *
     * @param onItemLongClickListener
     */
    fun setOnItemLongClickListener(onItemLongClickListener: com.lz.library.adapter.BaseAdapter.OnItemLongClickListener?) {
        this.onItemLongClickListener = onItemLongClickListener
    }

    /**  ------------------------------  public voids  ------------------------------------ */

    final override val data: MutableList<T> = mData

    final override val layoutInflater: LayoutInflater = mInflater

    final override fun getItem(position: Int): T = mData[position]

    final override fun isEmpty(): Boolean = mData.isEmpty()

    override fun setNewData(newData: List<T>) {
        if (mData.isEmpty()) {
            if (newData.isNotEmpty()) {
                mData.addAll(newData)
                notifyItemRangeInserted(0, newData.size)
            }
        } else {
            val preSize = mData.size
            mData.clear(); mData.addAll(newData)
            val diff = mData.size - preSize
            when {
                diff == 0 -> notifyItemRangeChanged(0, preSize)
                diff > 0 -> {
                    notifyItemRangeChanged(0, preSize); notifyItemRangeInserted(preSize, diff)
                }
                else -> {
                    notifyItemRangeRemoved(mData.size, -diff)
                    if (mData.isNotEmpty()) {
                        notifyItemRangeChanged(0, mData.size)
                    }
                }
            }
        }
    }

    override fun setNewData(newData: List<T>, diffResult: DiffResult) {
        diffResult.dispatchUpdatesTo(this)
        mData.clear()
        mData.addAll(newData)
    }

    override fun addData(addData: List<T>, notifyChanged: Boolean) {
        if (addData.isEmpty()) return
        val positionStart = mData.size
        mData.addAll(addData)
        if (notifyChanged) {
            notifyItemRangeInserted(positionStart, addData.size)
        }
    }

    override fun removeAll() {
        if (mData.isEmpty()) return
        val itemCount = mData.size
        mData.clear()
        notifyItemRangeRemoved(0, itemCount)
    }

    override fun addItem(position: Int, item: T, notifyChanged: Boolean) {
        if (position > mData.size || position < 0) return
        if (position == mData.size) mData.add(item) else mData.add(position, item)
        if (notifyChanged) notifyItemInserted(position)
    }

    override fun removeItem(position: Int, notifyChanged: Boolean) {
        if (position >= mData.size || position < 0) return
        mData.removeAt(position)
        if (notifyChanged) notifyItemRemoved(position)
    }

    interface OnItemClickListener {
        /**
         * @param view     viewholder itemview
         * @param position adapter position
         */
        fun onItemClick(view: View, position: Int)
    }

    interface OnItemLongClickListener {
        /**
         * @param view     viewholder itemview
         * @param position adapter position
         */
        fun onItemLongClick(view: View, position: Int): Boolean
    }

}